package com.music.glide.load.engine.bitmap_recycle


class KGroupLinkedMap<K : KPoolAble, V> {

    private val head by lazy { LinkedEntry<K, V>() }

    private val keyToEntry by lazy { HashMap<K, LinkedEntry<K, V>>() }

    /**
     * 新添加的在链表末尾,表示新回收的资源
     */
    fun put(key: K, value: V) {
        var linkedEntry: LinkedEntry<K, V>? = keyToEntry[key]
        if (linkedEntry == null) {
            linkedEntry = LinkedEntry(key)
            makeTail(linkedEntry)
            keyToEntry[key] = linkedEntry
        } else {
            key.offer()
        }
        linkedEntry.add(value)
    }

    /**
     * 访问过的添加在链表头部,表示最近使用过的
     */
    fun get(key: K): V? {
        var entry = keyToEntry[key]
        if (entry == null) {
            entry = LinkedEntry()
            keyToEntry[key] = entry
        } else {
            key.offer()
        }
        makeHead(entry)
        return entry.removeLast()
    }

    fun removeLast(): V? {
        var last = head.prev
        while (last !== head) {
            val removed = last.removeLast()
            if (removed != null) {
                return removed
            } else {
                removeEntry(last)
                keyToEntry.remove(last.key)
                last.key?.offer()
            }
            last = last.prev
        }
        return null
    }


    private fun makeHead(entry: LinkedEntry<K, V>) {
        removeEntry(entry)
        entry.prev = head
        entry.next = head.next
        updateEntry(entry)
    }


    private fun makeTail(entry: LinkedEntry<K, V>) {
        removeEntry(entry)
        entry.prev = head.prev
        entry.next = head
        updateEntry(entry)
    }

    private fun updateEntry(entry: LinkedEntry<K, V>) {
        entry.prev.next = entry
        entry.next.prev = entry
    }

    private fun removeEntry(entry: LinkedEntry<K, V>) {
        entry.prev.next = entry.next
        entry.next.prev = entry.prev
    }


    private class LinkedEntry<K, V>(val key: K? = null) {

        private var values: MutableList<V>? = null

        var next: LinkedEntry<K, V> = this

        var prev: LinkedEntry<K, V> = this

        fun removeLast(): V? {
            return if (size() > 0) {
                values!!.removeAt(size() - 1)
            } else {
                null
            }
        }

        fun size(): Int {
            return values?.size ?: 0
        }

        fun add(value: V) {
            if (values.isNullOrEmpty()) {
                values = mutableListOf()
            }
            values!!.add(value)
        }
    }
}